﻿/**************************************************************
*作者：Leon
*创建时间：2022/4/5 17:02:57
**************************************************************/
using System.Collections.ObjectModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Lad.DrawProject.Controls.Converters;

/// <summary>
/// 颜色笔刷转换器
/// </summary>
public class ColorBrushConverter : IValueConverter
{

    public object? Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Brush? brush = null;
        if (value is Color color)
        {
            brush = new SolidColorBrush(color);
        }
        else if (value is ColorObject colorObject)
        {
            switch (colorObject.BrushType)
            {
                case BrushType.None:
                    brush = new SolidColorBrush(Colors.Transparent);
                    break;
                case BrushType.SolidColorBrush:
                    brush = new SolidColorBrush(colorObject.Color);
                    break;
                case BrushType.LinearGradientBrush:
                    GetLinearOrientationPoint(colorObject.LinearOrientation, out var startPoint, out var endPoint);
                    {
                        var myBrush = new LinearGradientBrush() { StartPoint = startPoint, EndPoint = endPoint };
                        if (colorObject.GradientStop != null)
                        {
                            foreach (var stop in colorObject.GradientStop)
                            {
                                myBrush.GradientStops.Add(new System.Windows.Media.GradientStop(stop.Color, stop.Offset));
                            }
                        }
                        brush = myBrush;
                        RotateTransform rotateTransform = new(colorObject.Angle, 0.5, 0.5);
                        myBrush.RelativeTransform = rotateTransform;
                    }
                    break;
                case BrushType.RadialGradientBrush:
                    Point center;
                    Point gradientOrigin;
                    double radiusX = 1;
                    double radiusY = 1;

                    if (colorObject.RadialOrientation == RadialOrientation.LeftTop)
                    {
                        center = new Point(0, 0);
                        gradientOrigin = center;

                    }
                    else if (colorObject.RadialOrientation == RadialOrientation.RightTop)
                    {
                        center = new Point(1, 0);
                        gradientOrigin = center;

                    }
                    else if (colorObject.RadialOrientation == RadialOrientation.RightBottom)
                    {
                        center = new Point(1, 1);
                        gradientOrigin = center;

                    }
                    else if (colorObject.RadialOrientation == RadialOrientation.LeftBottom)
                    {
                        center = new Point(0, 1);
                        gradientOrigin = center;
                    }
                    else
                    {
                        center = new Point(0.5, 0.5);
                        gradientOrigin = center;
                        radiusX = 0.5;
                        radiusY = 0.5;
                    }

                    {
                        var myBrush = new RadialGradientBrush
                        {
                            Center = center,
                            GradientOrigin = gradientOrigin,
                            RadiusX = radiusX,
                            RadiusY = radiusY
                        };
                        if (colorObject.GradientStop != null)
                        {
                            foreach (var stop in colorObject.GradientStop)
                            {
                                myBrush.GradientStops.Add(new System.Windows.Media.GradientStop(stop.Color, stop.Offset));
                            }
                        }
                        brush = myBrush;

                        var rotateTransform = new RotateTransform(colorObject.Angle, 0.5, 0.5);
                        myBrush.RelativeTransform = rotateTransform;
                    }

                    break;
                case BrushType.ImageBrush:
                    if (!string.IsNullOrEmpty(colorObject.Image))
                        brush = new ImageBrush() { ImageSource = new BitmapImage(new Uri(colorObject.Image, UriKind.Absolute)) };
                    break;
                case BrushType.VisualBrush:
                    break;
                case BrushType.DrawingBrush:
                    GeometryDrawing backgroundSquare =
                        new(
                            Brushes.White,
                            null,
                            new RectangleGeometry(new Rect(0, 0, 100, 100)));

                    GeometryGroup aGeometryGroup = new();
                    aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(0, 0, 50, 50)));
                    aGeometryGroup.Children.Add(new RectangleGeometry(new Rect(50, 50, 50, 50)));

                    LinearGradientBrush checkerBrush = new();
                    checkerBrush.GradientStops.Add(new System.Windows.Media.GradientStop(Colors.Black, 0.0));
                    checkerBrush.GradientStops.Add(new System.Windows.Media.GradientStop(Colors.Gray, 1.0));

                    GeometryDrawing checkers = new(checkerBrush, null, aGeometryGroup);

                    DrawingGroup checkersDrawingGroup = new();
                    checkersDrawingGroup.Children.Add(backgroundSquare);
                    checkersDrawingGroup.Children.Add(checkers);
                    brush = new DrawingBrush()
                    {
                        Drawing = checkersDrawingGroup,
                        Viewport = new Rect(0, 0, 0.25, 0.25),
                        TileMode = TileMode.Tile
                    };
                    break;
                default:
                    break;
            }

            if (brush != null)
            {
                brush.Opacity = colorObject.Opacity;
            }
        }
        else if (value is ObservableCollection<GradientStop> gradientStop)
        {
            LinearGradientBrush myBrush = new() { StartPoint = new(0, 0.5), EndPoint = new(1, 0.5) };
            if (gradientStop != null)
            {
                foreach (var stop in gradientStop)
                {
                    myBrush.GradientStops.Add(new System.Windows.Media.GradientStop(stop.Color, stop.Offset));
                }
            }
            brush = myBrush;
        }

        return brush;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private void GetLinearOrientationPoint(LinearOrientation linearOrientation, out Point startPoint, out Point endPoint)
    {
        switch (linearOrientation)
        {
            case LinearOrientation.LeftToRight:
                startPoint = new Point(0, 0.5);
                endPoint = new Point(1, 0.5);
                break;
            case LinearOrientation.LeftTopToRightBottom:
                startPoint = new Point(0, 0);
                endPoint = new Point(1, 1);
                break;
            case LinearOrientation.TopToBottom:
                startPoint = new Point(0.5, 0);
                endPoint = new Point(0.5, 1);
                break;
            case LinearOrientation.RightTopToLeftBottom:
                startPoint = new Point(1, 0);
                endPoint = new Point(0, 1);
                break;
            case LinearOrientation.RightToLeft:
                startPoint = new Point(1, 0.5);
                endPoint = new Point(0, 0.5);
                break;
            case LinearOrientation.RightBottomToLeftTop:
                startPoint = new Point(1, 1);
                endPoint = new Point(0, 0);
                break;
            case LinearOrientation.BottomToTop:
                startPoint = new Point(0.5, 1);
                endPoint = new Point(0.5, 0);
                break;
            case LinearOrientation.LeftBottomToRightTop:
                startPoint = new Point(0, 1);
                endPoint = new Point(1, 0);
                break;
            default:
                startPoint = new Point(0, 0.5);
                endPoint = new Point(1, 0.5);
                break;
        }
    }
}
